package com.qen.conditions;

import cn.hutool.core.collection.CollectionUtil;
import com.qen.interfaces.CompareBase;
import com.qen.interfaces.FuncBase;
import com.qen.interfaces.JoinBase;
import com.qen.interfaces.Nested;
import com.qen.wrapper.AbstractWrapper;
import com.qen.wrapper.SharedString;
import com.qen.wrapper.Wrapper;
import com.qen.wrapper.segments.MergeSegments;
import org.beetl.sql.clazz.kit.BeetlSQLException;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiPredicate;
import java.util.function.Consumer;

/**
 * @author licz
 * @data 2025年05月26日 8:52 AM
 */
public abstract class AbstractChainWrapper<T, R, Children extends AbstractChainWrapper<T, R, Children, Param>, Param extends AbstractWrapper<T, R, Param>>
        extends Wrapper<T>
        implements CompareBase<Children, R>, FuncBase<Children, R>, JoinBase<Children>, Nested<Param, Children> {

    protected final Children typedThis = (Children) this;
    /**
     * 子类所包装的具体 Wrapper 类型
     */
    protected Param wrapperChildren;
    /**
     * 查询表
     */
    protected final SharedString from = new SharedString();

    /**
     * 必须的构造函数
     */
    public AbstractChainWrapper() {
    }

    public AbstractWrapper<T, R, Param> getWrapper() {
        return wrapperChildren;
    }

    public Children setEntity(T entity) {
        getWrapper().setEntity(entity);
        return typedThis;
    }

    public Children setEntityClass(Class<T> entityClass) {
        getWrapper().setEntityClass(entityClass);
        return typedThis;
    }

    @Override
    public <V> Children allEq(boolean condition, Map<R, V> params, boolean null2IsNull) {
        getWrapper().allEq(condition, params, null2IsNull);
        return typedThis;
    }

    @Override
    public <V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
        getWrapper().allEq(condition, filter, params, null2IsNull);
        return typedThis;
    }

    @Override
    public Children eq(boolean condition, R column, Object val) {
        getWrapper().eq(condition, column, val);
        return typedThis;
    }

    @Override
    public Children ne(boolean condition, R column, Object val) {
        getWrapper().ne(condition, column, val);
        return typedThis;
    }

    @Override
    public Children gt(boolean condition, R column, Object val) {
        getWrapper().gt(condition, column, val);
        return typedThis;
    }

    @Override
    public Children ge(boolean condition, R column, Object val) {
        getWrapper().ge(condition, column, val);
        return typedThis;
    }

    @Override
    public Children lt(boolean condition, R column, Object val) {
        getWrapper().lt(condition, column, val);
        return typedThis;
    }

    @Override
    public Children le(boolean condition, R column, Object val) {
        getWrapper().le(condition, column, val);
        return typedThis;
    }

    @Override
    public Children between(boolean condition, R column, Object val1, Object val2) {
        getWrapper().between(condition, column, val1, val2);
        return typedThis;
    }

    @Override
    public Children notBetween(boolean condition, R column, Object val1, Object val2) {
        getWrapper().notBetween(condition, column, val1, val2);
        return typedThis;
    }

    @Override
    public Children like(boolean condition, R column, Object val) {
        getWrapper().like(condition, column, val);
        return typedThis;
    }

    @Override
    public Children likeLeft(boolean condition, R column, Object val) {
        getWrapper().likeLeft(condition, column, val);
        return typedThis;
    }

    @Override
    public Children likeRight(boolean condition, R column, Object val) {
        getWrapper().likeRight(condition, column, val);
        return typedThis;
    }

    @Override
    public Children notLike(boolean condition, R column, Object val) {
        getWrapper().notLike(condition, column, val);
        return typedThis;
    }

    @Override
    public Children notLikeLeft(boolean condition, R column, Object val) {
        getWrapper().notLikeLeft(condition, column, val);
        return typedThis;
    }

    @Override
    public Children notLikeRight(boolean condition, R column, Object val) {
        getWrapper().notLikeRight(condition, column, val);
        return typedThis;
    }

    @Override
    public Children isNull(boolean condition, R column) {
        getWrapper().isNull(condition, column);
        return typedThis;
    }

    @Override
    public Children isNotNull(boolean condition, R column) {
        getWrapper().isNotNull(condition, column);
        return typedThis;
    }

    @Override
    public Children in(boolean condition, R column, Collection<?> coll) {
        getWrapper().in(condition, column, coll);
        return typedThis;
    }

    @Override
    public Children in(boolean condition, R column, Object... values) {
        getWrapper().in(condition, column, values);
        return typedThis;
    }

    @Override
    public Children notIn(boolean condition, R column, Collection<?> coll) {
        getWrapper().notIn(condition, column, coll);
        return typedThis;
    }

    @Override
    public Children notIn(boolean condition, R column, Object... values) {
        getWrapper().notIn(condition, column, values);
        return typedThis;
    }

    @Override
    public Children eqSql(boolean condition, R column, String eqValue) {
        getWrapper().eqSql(condition, column, eqValue);
        return typedThis;
    }

    @Override
    public Children inSql(boolean condition, R column, String inValue) {
        getWrapper().inSql(condition, column, inValue);
        return typedThis;
    }

    @Override
    public Children gtSql(boolean condition, R column, String inValue) {
        getWrapper().gtSql(condition, column, inValue);
        return typedThis;
    }

    @Override
    public Children geSql(boolean condition, R column, String inValue) {
        getWrapper().geSql(condition, column, inValue);
        return typedThis;
    }

    @Override
    public Children ltSql(boolean condition, R column, String inValue) {
        getWrapper().ltSql(condition, column, inValue);
        return typedThis;
    }

    @Override
    public Children leSql(boolean condition, R column, String inValue) {
        getWrapper().leSql(condition, column, inValue);
        return typedThis;
    }

    @Override
    public Children notInSql(boolean condition, R column, String inValue) {
        getWrapper().notInSql(condition, column, inValue);
        return typedThis;
    }

    @Override
    @SafeVarargs
    public final Children groupBy(boolean condition, R column, R... columns) {
        return doGroupBy(condition, column, CollectionUtil.toList(columns));
    }

    @Override
    public Children groupBy(boolean condition, R column, List<R> columns) {
        return doGroupBy(condition, column, columns);
    }

    @Override
    public Children groupBy(boolean condition, R column) {
        return doGroupBy(condition, column, null);
    }

    @Override
    public Children groupBy(boolean condition, List<R> columns) {
        return doGroupBy(condition, null, columns);
    }

    @Override
    @SafeVarargs
    public final Children orderBy(boolean condition, boolean isAsc, R column, R... columns) {
        return orderBy(condition, isAsc, column, CollectionUtil.toList(columns));
    }

    @Override
    public Children orderBy(boolean condition, boolean isAsc, R column, List<R> columns) {
        return doOrderBy(condition, isAsc, column, columns);
    }

    @Override
    @SafeVarargs
    public final Children groupBy(R column, R... columns) {
        return doGroupBy(true, column, CollectionUtil.toList(columns));
    }

    @Override
    @SafeVarargs
    public final Children orderByAsc(R column, R... columns) {
        return orderByAsc(true, column, columns);
    }

    @Override
    @SafeVarargs
    public final Children orderByAsc(boolean condition, R column, R... columns) {
        return doOrderByAsc(condition, column, CollectionUtil.toList(columns));
    }

    @Override
    @SafeVarargs
    public final Children orderByDesc(boolean condition, R column, R... columns) {
        return doOrderByDesc(condition, column, CollectionUtil.toList(columns));
    }

    @Override
    @SafeVarargs
    public final Children orderByDesc(R column, R... columns) {
        return orderByDesc(true, column, columns);
    }

    // --------------  新增重写方法开始----------------
    protected Children doOrderByDesc(boolean condition, R column, List<R> columns) {
        return doOrderBy(condition, false, column, columns);
    }

    protected Children doOrderByAsc(boolean condition, R column, List<R> columns) {
        return doOrderBy(condition, true, column, columns);
    }

    protected Children doOrderBy(boolean condition, boolean isAsc, R column, List<R> columns) {
        getWrapper().doOrderBy(condition, isAsc, column, columns);
        return typedThis;
    }

    protected Children doGroupBy(boolean condition, R column, List<R> columns) {
        getWrapper().doGroupBy(condition, column, columns);
        return typedThis;
    }


    // --------------  新增重写方法结束----------------

    @Override
    public Children orderBy(boolean condition, boolean isAsc, R column) {
        return doOrderBy(condition, isAsc, column, null);
    }

    @Override
    public Children orderBy(boolean condition, boolean isAsc, List<R> columns) {
        return doOrderBy(condition, isAsc, null, columns);
    }

    @Override
    public Children having(boolean condition, String sqlHaving, Object... params) {
        getWrapper().having(condition, sqlHaving, params);
        return typedThis;
    }

    @Override
    public Children func(boolean condition, Consumer<Children> consumer) {
        if (condition) {
            consumer.accept(typedThis);
        }
        return typedThis;
    }

    @Override
    public Children or(boolean condition) {
        getWrapper().or(condition);
        return typedThis;
    }

    @Override
    public Children apply(boolean condition, String applySql, Object... values) {
        getWrapper().apply(condition, applySql, values);
        return typedThis;
    }

    @Override
    public Children last(boolean condition, String lastSql) {
        getWrapper().last(condition, lastSql);
        return typedThis;
    }

    @Override
    public Children comment(boolean condition, String comment) {
        getWrapper().comment(condition, comment);
        return typedThis;
    }

    @Override
    public Children first(boolean condition, String firstSql) {
        getWrapper().first(condition, firstSql);
        return typedThis;
    }

    @Override
    public Children exists(boolean condition, String existsSql, Object... values) {
        getWrapper().exists(condition, existsSql, values);
        return typedThis;
    }

    @Override
    public Children notExists(boolean condition, String existsSql, Object... values) {
        getWrapper().notExists(condition, existsSql, values);
        return typedThis;
    }

    @Override
    public Children and(boolean condition, Consumer<Param> consumer) {
        getWrapper().and(condition, consumer);
        return typedThis;
    }

    @Override
    public Children or(boolean condition, Consumer<Param> consumer) {
        getWrapper().or(condition, consumer);
        return typedThis;
    }

    @Override
    public Children nested(boolean condition, Consumer<Param> consumer) {
        getWrapper().nested(condition, consumer);
        return typedThis;
    }

    @Override
    public Children not(boolean condition, Consumer<Param> consumer) {
        getWrapper().not(condition, consumer);
        return typedThis;
    }

    @Override
    public String getSqlSegment() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getSqlSegment"));
    }

    @Override
    public String getSqlFirst() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getSqlFirst"));
    }

    @Override
    public String getSqlSelect() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getSqlSelect"));
    }

    @Override
    public String getSqlSet() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getSqlSet"));
    }

    @Override
    public String getSqlComment() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getSqlComment"));
    }

    @Override
    public String getTargetSql() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getTargetSql"));
    }

    @Override
    public T getEntity() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getEntity"));
    }

    @Override
    public MergeSegments getExpression() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getExpression"));
    }

    @Override
    public String getCustomSqlSegment() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getCustomSqlSegment"));
    }

    @Override
    public void clear() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "clear"));
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "clone"));
    }

    @Override
    public Map<String, Object> getParam() {
        throw new BeetlSQLException(BeetlSQLException.ERROR, String.format("can not use this method for \"%s\"", "getParam"));
    }

    /**
     * 获取连表部分语句
     */
    public String getFrom() {
        return "";
    }
}
